#include "rtc_drv.h"

/**
 * @desc  : 把RTC时间转成时间戳
 * @date  : 2025-04-06
 * @author: AnRui
 * @param : time - {参数说明}:
 * @return: uint32_t
 * @note  :
 */
static uint32_t ConvertRtcToTimestamp(const RtcTime_t* time) {
    struct  tm tmInfo;
    time_t timeStamp;
    memset(&tmInfo, 0, sizeof(tmInfo));
    tmInfo.tm_year = time->year - 1900;
    tmInfo.tm_mon = time->month - 1;
    tmInfo.tm_mday = time->day;
    tmInfo.tm_hour = time->hour;
    tmInfo.tm_min = time->minute;
    tmInfo.tm_sec = time->second;
    timeStamp = mktime(&tmInfo);
    return timeStamp;
}


/**
 * @desc  : 设置RTC时间
 * @date  : 2025-04-06
 * @author: AnRui
 * @param : time - {参数说明}:
 * @note  :
 */
void SetRtcTime(const RtcTime_t* time) {
    /* 等待上次对 RTC 寄存器写操作完成 */
    rtc_lwoff_wait();
    /* 设置时间*/
    rtc_counter_set(ConvertRtcToTimestamp(time) - TIMEZONE_OFFSET_SECONDS);
}

/**
 * @desc  : RTC时钟初始化
 * @date  : 2025-04-06
 * @author: AnRui
 * @note  :
 */
void RtcDrvInit(const RtcTime_t* time) {
    // 判断RTC 配置信息是否存在
    if (bkp_read_data(BKP_DATA_0) != MAGIC_CODE) {
        /* 使能对RTC的访问，使能PMU和BKP时钟 */
        rcu_periph_clock_enable(RCU_PMU);
        rcu_periph_clock_enable(RCU_BKPI);
        /* 使能对后备寄存器和RTC的写权限 */
        pmu_backup_write_enable();
        /* 复位后备寄存器 */
        bkp_deinit();
        /* 使能LXTAL，并等待其稳定 */
        rcu_osci_on(RCU_LXTAL);
        rcu_osci_stab_wait(RCU_LXTAL);
        /* 设置RTC时钟源为LXTAL */
        rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
        /* 使能RTC时钟 */
        rcu_periph_clock_enable(RCU_RTC);
        /* 等待APB1接口时钟和RTC时钟同步 */
        rtc_register_sync_wait();
        /* 等待上次对 RTC 寄存器写操作完成 */
        rtc_lwoff_wait();
        /* 设置分频值32767 */
        rtc_prescaler_set(32767);
        /* 设置时间*/
        SetRtcTime(time);
        // 往后备区域 某一个寄存器写一个码值
        bkp_write_data(BKP_DATA_0, MAGIC_CODE);
        return;
    }
    /* 使能对RTC的访问，使能PMU和BKP时钟 */
    rcu_periph_clock_enable(RCU_PMU);
    rcu_periph_clock_enable(RCU_BKPI);
    /* 使能对后备寄存器和RTC的写权限 */
    pmu_backup_write_enable();
    /* 等待APB1接口时钟和RTC时钟同步 */
    rtc_register_sync_wait();
}


/**
 * @desc  : 获取RTC时钟时间
 * @date  : 2025-04-06
 * @author: AnRui
 * @param : time - {参数说明}:
 * @note  :
 */
void GetRtcTime(RtcTime_t* time) {
    time_t timeStamp;
    struct tm* tmInfo;
    // 获取的是0时区的时间  +8个小时是北京时间
    timeStamp = rtc_counter_get() + 8 * 60 * 60;
    tmInfo = localtime(&timeStamp);
    time->year = tmInfo->tm_year + 1900;
    time->month = tmInfo->tm_mon + 1;
    time->day = tmInfo->tm_mday;
    time->hour = tmInfo->tm_hour;
    time->minute = tmInfo->tm_min;
    time->second = tmInfo->tm_sec;
}


/**
 * @desc  : RTC中断开启
 * @date  : 2025-04-06
 * @author: AnRui
 * @note  :
 */
static void RtcInterruptEnable(void) {
    exti_flag_clear(EXTI_17);
    exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING);
    rtc_interrupt_enable(RTC_INT_ALARM);
    rtc_flag_clear(RTC_FLAG_ALARM);
    nvic_irq_enable(RTC_Alarm_IRQn, RtcIrqPriority);
}

/**
 * @desc  : 设置闹钟时间
 * @date  : 2025-04-06
 * @author: AnRui
 * @param : time - {参数说明}:
 * @note  :
 */
void SetRtcAlarm(const RtcTime_t* time) {
    rtc_lwoff_wait();
    rtc_alarm_config(ConvertRtcToTimestamp(time) - TIMEZONE_OFFSET_SECONDS);
}

/**
 * @desc  : RTC闹钟初始化
 * @date  : 2025-04-06
 * @author: AnRui
 * @param : time - {参数说明}:
 * @note  :
 */
void RtcAlarmInit(const RtcTime_t* time) {
    RtcInterruptEnable();
    SetRtcAlarm(time);
}


/**
 * @desc  : RTC中断回调函数
 * @date  : 2025-04-06
 * @author: AnRui
 * @note  :
 */
void RTC_Alarm_IRQHandler() {
    if (rtc_flag_get(RTC_FLAG_ALARM) == SET) {
        rtc_flag_clear(RTC_FLAG_ALARM);
        exti_flag_clear(EXTI_17);
        printf("RTC ALARTM TRIGGER\n");
    }
}




